<?xml version="1.0" encoding="UTF-8"?>
<html>
    <head>
        <link type="text/css" rel="stylesheet" href="./css/template.css" />
        <link type="text/css" rel="stylesheet" href="./css/SyntaxHighlighter.css" />
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>L'API Lucene</title>
        <script language="javascript" src="./js/shInit.js" />
        <script language="javascript" src="./js/shCore.js" />
        <script language="javascript" src="./js/shBrushCpp.js" />
        <script language="javascript" src="./js/shBrushCSharp.js" />
        <script language="javascript" src="./js/shBrushCss.js" />
        <script language="javascript" src="./js/shBrushDelphi.js" />
        <script language="javascript" src="./js/shBrushJava.js" />
        <script language="javascript" src="./js/shBrushJScript.js" />
        <script language="javascript" src="./js/shBrushPhp.js" />
        <script language="javascript" src="./js/shBrushPython.js" />
        <script language="javascript" src="./js/shBrushRuby.js" />
        <script language="javascript" src="./js/shBrushSql.js" />
        <script language="javascript" src="./js/shBrushVb.js" />
        <script language="javascript" src="./js/shBrushXml.js" />
        <keywords>Lucene,API,API Lucene,LGPL,Lucene Java,Nutch,Hadoop,Lucene4c,Apache Lucene</keywords>
        <author>Philippe DUVERGER</author>
    </head>
    <body>
        <div class="chapter">
            <center>
                <img src="./images/lucene_logo.jpg" />
            </center>
            <h2>1 - Introduction</h2>
            <p>Avec l’expansion du volume de données sur tout système informatique, il est souvent nécessaire de pouvoir chercher et retrouver rapidement et facilement ce que l’on a besoin.</p>
            <p>Lors de la programmation de n’importe quelle application, la fonction de recherche est souvent fastidieuse à développer, ne correspond pas toujours à ce que l’on a besoin et est difficile à faire évoluer.</p>
            <p>C’est pourquoi la fondation Apache a développé une API : Apache Lucene qui une bibliothèque de moteur de recherche complète et de haute-performance écrit entièrement en java. C’est une technologie adaptée pour presque n’importe quelle application qui a besoin d’une recherche intégrale du texte sur plate-forme diverses.</p>
        </div>
        <div class="chapter">
            <h2>2 - Découverte de l’API Lucene</h2>
            <p>Lucene est une API permettant de créer facilement des applications de recherche</p>
            <p>Les avantages de Lucene est qu’il est flexible, puissant et facile à utiliser.</p>
            <p>Lucene est disponible avec une licence gratuite open-source LGPL.</p>
            <p>Notez que Lucene est une API, ce qui veux dire que tout les cotés difficiles ont été implémentés, et qu’il ne vous reste plus que le plus simple.</p>
            <p>Vous pouvez alors facilement développer une application de recherche personnalisée, parfaitement adapté à vos besoins.</p>
            <p>Notons également que le projet apache-Lucene développe des outils open-source de recherche comprenant entre autre :</p>
            <p />
            <ul>
                <li>Lucene Java, permettant une indexation et une technologie de recherche basée sur java.</li>
                <li>Nutch basé sur Lucene qui permet une application de recherche web.</li>
                <li>Hadoop qui est une plate forme distribuée utilisée par Nutch.</li>
                <li>Lucene4c est un moteur de recherche basé sur du C compatible avec Lucene Java, construit sur le runtime portable de apache.</li>
            </ul>
            <div class="subChapter">
                <h3>2.1 - Ce que fait l’API Lucene</h3>
                <p>Avec l’API Lucene, il est possible de :</p>
                <p />
                <ul>
                    <li>Générer des index à partir de documents.</li>
                    <li>Effectuer des recherches à partir des index créés.</li>
                    <li>Supprimer des index.</li>
                </ul>
            </div>
            <div class="subChapter">
                <h3>2.2 - Les packages</h3>
                <p>Voici un détail des principaux paquetages et ce qu’ils représentent :</p>
                <p>
                    <b>org.apache.lucene</b>
                    : package de plus haut niveau
                    <br />
                    <b>org.apache.lucene.analysis</b>
                    : API et code pour convertir texte et index.
                    <br />
                    <b>org.apache.lucene.analysis.standard</b>
                    : Un indexeur basé sur la grammaire construit avec javaCC
                    <br />
                    <b>org.apache.lucene.document</b>
                    : Les documents indexés
                </p>
                <p>
                    <b>org.apache.lucene.index</b>
                    : Code pour manipuler les index.
                    <br />
                    <b>org.apache.lucene.queryParser</b>
                    : Un simple parseur de requêtes.
                    <br />
                    <b>org.apache.lucene.search</b>
                    : Recherche d’index.
                </p>
                <p>
                    <b>org.apache.lucene.util</b>
                    : Quelques classes contenant des outils.
                </p>
            </div>
            <div class="subChapter">
                <h3>2.3 - Le projet Lucene</h3>
                <p>
                    Vous pourrez trouver l’API, toute la documentation dont vous avez besoin, ainsi que des utilisations avancées, sur le site d’apache dans partie Lucene à l’url suivante :
                    <a href="http://lucene.apache.org/java/docs/index.html" target="”_blank”">Doc Apache Lucene</a>
                </p>
            </div>
        </div>
        <div class="chapter">
            <h2>3 - Présentation des classes importantes de l’API Lucene</h2>
            <div class="subChapter">
                <h3>3.1 - L’analyseur</h3>
                <textarea name="code" class="java">org.apache.lucene.analysis.Analyzer;
					org.apache.lucene.analysis.standard.StandardAnalyzer;</textarea>
                <p>L’analyseur, souvent utilisé avec l’analyseur standard convertit toutes les chaînes de caractères en minuscule, et filtre les mots et caractères inutiles. Par mots et caractères inutiles on entend les mots commun du langage comme les articles (de, du, le, la, etc.…) et autres chaines de caractères qu’il est inutile de rechercher.</p>
                <p>Notons que les règles sont différentes du langage et vous devez utiliser l’analyseur correspondant à la langue utilisée.</p>
            </div>
            <div class="subChapter">
                <h3>3.2 - IndexWriter</h3>
                <textarea name="code" class="java">org.apache.lucene.index.IndexWriter;</textarea>
                <p>La classe indexWriter est la classe principale responsable de créer les index. Pour l’utiliser vous devez l’instancier avec un chemin ou peuvent être écrits les index. Si ce chemin n’existe pas, celui-ci sera créé, sinon il rafraichira l’index existant. Vous devez également lui passer une instance d’un analyseur.</p>
                <textarea name="code" class="java">org.apache.lucene.analysis.Analyzer;</textarea>
            </div>
            <div class="subChapter">
                <h3>3.3 - Document et Field</h3>
                <textarea name="code" class="java">org.apache.lucene.document.Document;
					org.apache.lucene.document.Field;</textarea>
                <p>
                    Document est la représentation d’un document indexé par Lucene.
                    <br />
                    Celui contient des sections appelées Fields qui vont contenir les valeurs indexées (comme par exemple une date, un texte, une chaîne de caractères, etc.…). Il est possible de spécifier comment les valeurs sont enregistrées et analysées par l’analyseur, comme par exemple il est possible de spécifier que la valeur ne soit pas utilisée comme critère de recherche (
                    <i>UN_TOKENIZED</i>
                    ).
                </p>
            </div>
            <div class="subChapter">
                <h3>3.4 - Query et QueryParser</h3>
                <textarea name="code" class="java">org.apache.lucene.queryParser.QueryParser;
					org.apache.lucene.search.Query;</textarea>
                <p>QueryParser permet de parser une requête permettant d’effectuer des opérations complexes. Le queryparser est construit avec un analyseur pour interpréter votre requête, de la même manière qu’un index en retirant les mots et caractères inutiles.</p>
                <p>La grammaire BNF du parsage d’une requête est la suivante :</p>
                <textarea name="code" class="java">
                    Query  ::= ( Clause )*
					Clause ::= ["+", "-"] [
                    <term>
                        ":"] (
                        <term>| "(" Query ")" )</term>
                    </term>
                </textarea>
                <p>
                    Pour plus d’informations sur les opérateurs, se reporter à la documentation officielle à l’adresse suivante :
                    <br />
                    <a href="http://lucene.apache.org/java/docs/queryparsersyntax.html" target="”_blank”">donnant le détail complet sur les requêtes</a>
                    .
                </p>
                <p>Query est la classe abstraite pour les requêtes.</p>
            </div>
            <div class="subChapter">
                <h3>3.5 - Searcher, IndexSearcher et Hits</h3>
                <textarea name="code" class="java">org.apache.lucene.search.Hits;
					org.apache.lucene.search.IndexSearcher;
					org.apache.lucene.search.Searcher;</textarea>
                <p>Searcher et IndexSearcher permet d’effectuer des recherches sur l’ensemble des index, il suffit de leur passer les fichiers d’index.</p>
                <p>Le résultat de la recherche est retourné grâce à la méthode search de la classe Searcher et retourne une collection de Hit contenant la liste des documents correspondant sur lequel il faut itérer.</p>
                <p />
                <ul>
                    <li>Query</li>
                    <li>QueryParser</li>
                    <li>Analyzer</li>
                    <li>Searcher</li>
                    <li>IndexSearcher</li>
                    <li>Hits</li>
                </ul>
                <center>
                    <img src="./images/lucene_recherche.jpg" />
                </center>
            </div>
        </div>
        <div class="chapter">
            <h2>4 - Utilisation des classes</h2>
            <p>Nous allons voir une petite application qui permettra d’indexer des fichiers textes puis chercher les fichiers à partir de mots</p>
            <p>Ces classes sont issues des exemples donnés comme démonstration par les créateurs du projet mais qui ont été simplifiées afin de se consacrer uniquement à la plus simple utilisation de Lucene. Cet exemple comprend 3 classes :</p>
            <ul>
                <li>
                    Une pour convertir les objets fichier en document indexable :
                    <i>FileDocument</i>
                </li>
                <li>
                    Une pour indexer des documents à partir de fichiers :
                    <i>FileIndexer</i>
                </li>
                <li>
                    Une pour rechercher les index précédemment créés:
                    <i>FileSearcher</i>
                </li>
            </ul>
            <div class="subChapter">
                <h3>4.1 - FileDocument</h3>
                <p>Pour indexer les fichiers, ceux-ci doivent être des documents, il faut donc tout d’abord les convertir. Le document (org.apache.lucene.document.Document) représente un document auquel il est possible d’ajouter des champs (org.apache.lucene.document.Field). Dans l’exemple suivant, nous créons un document à partir d’un fichier à partir duquel nous indexons son chemin, son nom et son contenu.</p>
                <textarea name="code" class="java">package main;
					import java.io.File;
					import java.io.FileNotFoundException;
					import java.io.FileReader;
					import org.apache.lucene.document.Document;
					import org.apache.lucene.document.Field;
					public class FileDocument {
					/**
					* Lucene peut seulement indexer des objets de type document
					* Donc les fichiers sont convertit en document selon ce que l'on veut indexer
					*/
					public static Document Document(File file) throws FileNotFoundException {
					//le document que nous allons remplir
					Document doc = new Document();
					//ajoute le champ contenant le chemin du fichier.
					//le champ sera indexé  Field.Store.YES
					//mais pas tokenizé ( séparé en chaine plus petite )
					doc.add(new Field("path", file.getPath(), Field.Store.YES, Field.Index.UN_TOKENIZED));
					doc.add(new Field("name", file.getName(), Field.Store.YES, Field.Index.UN_TOKENIZED));
					//ajoute le contenu du fichier
					doc.add(new Field("content", new FileReader(file)) );
					//retourne le document
					return doc;
					}</textarea>
            </div>
            <div class="subChapter">
                <h3>4.2 - FileIndexer</h3>
                <p>Dans cette partie, nous utilisons :</p>
                <p />
                <ul>
                    <li>Les IndexWriter pour indexer les documents</li>
                    <li>L’analyseur</li>
                </ul>
                <p>Voici l’implémentation utilisant les principes d’indexation : la classe FileIndexer a une méthode index qui obtient un fichier index qui peut être indexé.</p>
                <p>
                    Pour indexer un objet, le fichier doit être convertit en un document avec champs, qui peuvent être indexé à partir de la classe
                    <i>FileDocument</i>
                    précédemment créée.
                </p>
                <textarea name="code" class="java">package main;
					import java.io.File;
					import java.io.IOException;
					import org.apache.lucene.analysis.Analyzer;
					import org.apache.lucene.analysis.standard.StandardAnalyzer;
					import org.apache.lucene.index.IndexWriter;
					public class FileIndexer {
					/**
					* Convertit les objet indexé en document Et écrit le document avec  un indexWriter
					* @param le  fichier à indexé
					*/
					public static void index(File file, String baseIndex ) {
					try {
					// repertoire où sont stocké les fichiers d'index
					String indexFile = baseIndex;
					// ################# creation du writer ######################
					// le IndexWriter qui ecrira les documents
					IndexWriter writer = null;
					// créé le repertoire d'index si celui ci n'existe pas
					boolean create;
					File f = new File(indexFile);
					if (f.exists() &amp;&amp; f.isDirectory()) {
					create = false;
					} else {
					create = true;
					}
					// initialise le writer qui va etre utilise
					writer = new IndexWriter(indexFile, new  StandardAnalyzer(), create);
					// ################# ajoute le document ######################
					writer.addDocument(FileDocument.Document(file));
					writer.optimize();
					if (null != writer) {
					writer.close();
					}
					} catch (IOException e) {
					e.printStackTrace();
					}
					}
					}</textarea>
            </div>
            <div class="subChapter">
                <h3>4.3 - FileSearcher</h3>
                <p>La classe SearchFile est assez simple.</p>
                <p>Elle est utilisée avec :</p>
                <p />
                <ul>
                    <li>Un indexsearcher</li>
                    <li>Un StandardAnalyzer (utilisé aussi dans IndexFile)</li>
                    <li>Un queryparser</li>
                </ul>
                <p>L’objet query contient le résultat de QueryParser qui est passé au searcher. Le résultat du searcher est retourné dans une collection de document appelé « Hits » qui sont alors itéré et affichés à l’utilisateur.</p>
                <textarea name="code" class="java">package main;
					import java.io.IOException;
					import org.apache.lucene.analysis.Analyzer;
					import org.apache.lucene.analysis.standard.StandardAnalyzer;
					import org.apache.lucene.queryParser.ParseException;
					import org.apache.lucene.queryParser.QueryParser;
					import org.apache.lucene.search.Hits;
					import org.apache.lucene.search.IndexSearcher;
					import org.apache.lucene.search.Quer
					import org.apache.lucene.search.Searcher;
					public class FileSearcher
					{
					public  static void  search(String queryString, String baseIndex)
					{
					try
					{
					//créé un searcher à partir du fichier d'index
					String indexFile = baseIndex;
					Searcher searcher = new IndexSearcher(indexFile);
					//l'analyseur qui sera utilisé pour la requete
					Analyzer analyzer = new StandardAnalyzer();
					//recherche dans le champ content la valeur queryString avec l'analyseur
					Query query= QueryParser.parse(queryString, "content", analyzer);
					//obtient les hits à partir de la requete precedente
					Hits hits = searcher.search(query);
					//affiche les 10 premier résultat
					int start = 0;
					final int HITS_PER_PAGE = 10;
					int end = Math.min(HITS_PER_PAGE, hits.length());
					//Itére sur les résultats
					//Le résultat est un tableau de document
					System.out.println("Résultats : ");
					if (hits.length() &gt; 0)
					{
					for (int i = start; i
					&lt; end; i++)
					{
					System.out.println("Chemin :
					+ hits.doc(i).get("path").toString());
					System.out.println("Nom du fichier :
					+ hits.doc(i).get("name").toString());
					System.out.println();
					}
					}
					else
					{
					System.out.println("Aucun document trouvé.");
					}
					}
					catch (ParseException e)
					{
					e.printStackTrace();
					}
					catch (IOException e)
					{
					e.printStackTrace();
					}
					}
					}</textarea>
            </div>
            <div class="subChapter">
                <h3>4.4 - Test</h3>
                <p>
                    Pour tester le tout nous avons utilisé 5 fichiers textes que nous avons ajoutés au répertoire d’index
                    <i>baseIndex</i>
                    en appelant la fonction
                    <i>FileIndexer.index</i>
                    .
                </p>
                <p>Nous avons ensuite fait une recherche avec la fonction search.</p>
                <textarea name="code" class="java">
                    package main;
					import java.io.File;
					public class Launch
					{
                    <!--[if !supportLineBreakNewLine]-->
                    <!--[endif]-->
                    public static void main(String[] args)
					{
					//répertoire de base ou vont être contenu les fichiers d’index
					String baseIndex = "D:\\FichiersIndexe";
					FileIndexer.index(new File("c:\\1.txt"), baseIndex);
					FileIndexer.index(new File("c:\\2.txt"), baseIndex);
					FileIndexer.index(new File("c:\\3.txt"), baseIndex);
					FileIndexer.index(new File("c:\\4.txt"), baseIndex);
					FileIndexer.index(new File("c:\\5.txt"), baseIndex);
					//recherche des fichier ayant comme contenu la chaîne to
					FileSearcher.search("toto", baseIndex);
					}
					}
                </textarea>
                <p>
                    Voici la sortie de ce programme (en effet le fichier 5.txt contenait la chaine toto).
                    <br />
                    Résultats :
                    <br />
                    <i>Chemin : c:\5.txt</i>
                    <br />
                    <i>Nom du fichier : 5.txt</i>
                </p>
            </div>
        </div>
        <div class="chapter">
            <h2>5 - Conclusion</h2>
            <p>
                Nous avons pu voir que l’
                <i>API Lucene</i>
                nous à permit de créer très facilement une fonction de recherche avec très peu de code. De plus, ce qui a été développé peut évoluer facilement.
            </p>
            <p>L’API supporte maintenant 30 langues et peut être utilisée également dans un développement Web, mais aussi avec des flux RSS, document office (Word, PDF, PowerPoint, Excel, etc…) et autres, ce qui montre que les possibilités d’utilisation sont assez voir très vastes.</p>
        </div>
        <div class="chapter">
            <h2>6 - Sources</h2>
            <a href="http://lucene.apache.org" target="”_blank”">Apache Lucene</a>
            <br />
            <a href="http://lucene.apache.org/java/docs/api/index.html" target="”_blank”">Doc Apache Lucene</a>
        </div>
    </body>
</html>

